<?php

namespace App\Services;

use App\Models\ZPituitaryHospitalCustomSmsTemplate;
use App\Models\ZPituitaryPatientsNotice;
use App\Models\ZPituitaryUserContactRecords;
use App\Models\ZPituitaryUserVisitLevel;
use App\Models\ZPituitaryVisitRecords;
use App\Models\ZZMed\ZHospMember;
use Illuminate\Support\Facades\Log;

class VisitRemindService
{

    // 用户查询的就诊数量
    const LIMIT = 1000;

    /**
     *  生成提醒记录
     * @return bool
     */
    public static function flushNotice()
    {
        Log::info("remind_flush start time " . date("Y-m-d H:i:s"));
        $now = date('Y-m-d H:i:s');
        //更新倒计时时间
        ZPituitaryPatientsNotice::updatePatientNoticeCountDown();
        //看今天是否有预约和就诊和更改计划的
        $start = date("Y-m-d H:i:s", time() - 5400); //大于1.5小时之前的
        $end = date("Y-m-d H:i:s", time() + 1200); //担心处理时间过长 增加 20分钟预留
        //获取就诊人数列表
        $userList = ZPituitaryVisitRecords::getVisitList($start, $end);

        foreach ($userList as $one) {
            $userId = $one['user_id'];
            //获取用户院内唯一的数据记录
            $list = ZPituitaryVisitRecords::getUserVisitRecord(self::LIMIT, 0, $userId);
            foreach ($list as $item) {
                // 处理单条记录 并包含创建和更新时间
                $data = self::explainData($item);
                if ($data) {
                    // 去除表无效的字段
                    unset($data["visit_diff"], $data['min_visit_at'], $data['next_followup_tmp']);
                    ZPituitaryPatientsNotice::insertOnDuplicateKey($data);
                }
            }
        }
        Log::info('remind_flush  end time' . date("Y-m-d H:i:s"));
        return true;
    }

    /**
     *  默认-组合更新的数据
     * @param $item
     * @return mixed
     */
    public static function explainData($info)
    {

        $data["user_id"] = $info['user_id'] ?? 0;
        $data["hosp_id"] = $info['hosp_id'] ?? 0;
        $data["dept_id"] = $info['dept_id'] ?? 0;

        //首次就诊时间
        $firstVisit = ZPituitaryVisitRecords::getPatientInfoByUserId($data["user_id"], 'asc');

        if (empty($firstVisit)) {
            Log::info("用户无首次访视记录 user_id = " . $data["user_id"]);
            return false;
        }
        $data['first_visit_at'] = !empty($firstVisit) ? $firstVisit->visit_at : '0001-01-01';
        $data["min_visit_at"] = !empty($firstVisit) ? $firstVisit->visit_at : '0001-01-01'; //最小访视日期
        //获取最大访视阶段
        $visitLevel = ZPituitaryUserVisitLevel::getMaxVisitInfo($data["user_id"]);
        $maxVisitLevel = $visitLevel['visit_level'] ?? 0;
        //没有访视就跳出
        if (empty($maxVisitLevel)) {
            Log::info("用户无最大访视记录 user_id = " . $data["user_id"]);
            return false;
        }

        $data["visit_level"] = $visitLevel['visit_level'] ?? 1; //最大访视阶段
        $data["visit_at"] = $visitLevel['visit_at'] > '0001-01-01' ? $visitLevel['visit_at'] : '0001-01-01'; //最大访视日期

        //应到访视
        $visits = self::levelToVisitData($data["min_visit_at"], $data["visit_level"], 3, 3, 1, 0);
        //距离天数
        $data["visit_diff"] = $visits["visit_diff"] ?? 0;

        if ($visits["visit_diff"] >= 0) {
            //就诊
            $data["remaining_days"] = $visits["visit_diff"];
            $data["overlap_days"] = "-1";
            $data["type"] = 1;
        } else {
            //漏诊
            $data["remaining_days"] = "-1";
            $data["overlap_days"] = abs($visits["visit_diff"]);
            $data["type"] = 2;
        }

        //推荐就诊日期
        $data["suggest_reserva"] = $visits["visit_period_date"];

        //应到访视
        $data["visit"] = $visits["visit_period"];

        //最新就诊时间
        $lastVisit = ZPituitaryVisitRecords::getPatientInfoByUserId($data["user_id"]);
        $data['newest_visit_at'] = !empty($lastVisit) ? $lastVisit->visit_at : '0001-01-01';
        $data['newest_visit_level'] = !empty($lastVisit) ? $lastVisit->visit_level : '0';

        //联系状态
        $recodes = ZPituitaryUserContactRecords::getPatientStatus($data["hosp_id"], $data["dept_id"], $data["user_id"], $data['newest_visit_level']);

        $data["state"] = $recodes["status"] ?? 0;
        $data["count_down"] = $recodes['count_down'];
        $data["created_at"] = date("Y-m-d H:i:s");
        $data["updated_at"] = date("Y-m-d H:i:s");
        $data["sms_times"] = $recodes["sms_times"];

        //下次随访时间
        $data['next_followup_tmp'] = $recodes['next_followup'];
        $data['next_followup'] = $recodes['next_followup'] > '0001-01-01' ? $recodes['next_followup'] : $visits["visit_period_date"];

        $data['is_remind'] = 1; //默认提醒

        return $data;
    }

    /**
     * 根据当前V和规则 计算下一个V 跟应到访V无关
     * 2019-12-31更新
     */
    public static function levelToVisitData($mindate, $maxv, $first_level = 3, $deliter = 3, $period = 1, $actual_reserva = 0) {

        if ($maxv < 3) {
            $default = intval($deliter / 3);
            $visitPeriod = $default + 2;
            $visitNextDate = date("Y-m-d", strtotime("+$deliter month", strtotime($mindate)));
        } else if ($maxv >= 22) {
            $visitPeriod = 23;
            $visitNextDate = date("Y-m-d", strtotime("+60 month", strtotime($mindate)));
        } else {
            //所有V
            if ($deliter == 3) {
                $visitPeriod = $maxv + 1;
            } else if ($deliter == 6) {
                //半年
                $tempv = intval($maxv / 2) + 1;
                $visitPeriod = 2 * $tempv;
            } else if ($deliter == 12) {
                //整年
                if ($maxv <= 5) {
                    $visitPeriod = 6;
                } else if ($maxv <= 9) {
                    $visitPeriod = 10;
                } else if ($maxv <= 13) {
                    $visitPeriod = 14;
                } else if ($maxv <= 17) {
                    $visitPeriod = 18;
                } else if ($maxv <= 21) {
                    $visitPeriod = 22;
                }
            }


            $next = ($visitPeriod - 2) * 3;
            //5年期限  V23-V24
            if ($next >= 60) {
                $next = 60;
            }
            $visitNextDate = date("Y-m-d", strtotime("+$next month", strtotime($mindate)));
        }

        $visitDiffDate = (strtotime($visitNextDate) - strtotime(date("Y-m-d"))) / 86400;

        //如果有预约日期，按预约日期算
        if ($actual_reserva && $actual_reserva > '0001-01-01') {
            if ($actual_reserva >= date("Y-m-d")) {
                $visitDiffDate = (strtotime($actual_reserva) - strtotime(date("Y-m-d"))) / 86400;
            } else {
                $visitDiffDate = -1 * (strtotime(date("Y-m-d")) - strtotime($actual_reserva)) / 86400;
            }
        }

        return [
            "visit_period" => $visitPeriod,
            "visit_diff" => $visitDiffDate, //相差天数
            "visit_period_date" => $visitNextDate //推荐就诊
        ];
    }


    //计算周期
    public static function periodInfo($periodType, $period, $data)
    {

        if (!empty($periodType)) {
            switch ($periodType) {
                case 1://按上次访视,隐藏应到访视，更新推荐就诊时间，距离天数
                    $lastVisitAt = $data["visit_at"];
                    $visitNextDate = date('Y-m-d', strtotime("$lastVisitAt +$period days")); //推荐就诊时间
                    $data["suggest_reserva"] = $visitNextDate;
                    $data['next_followup'] = $data['next_followup_tmp'] > '0001-01-01' ? $data['next_followup_tmp'] : $visitNextDate;
                    $data["visit_diff"] = $data["actual_reserva"] > '0001-01-01' ? $data["visit_diff"] : (strtotime($visitNextDate) - strtotime(date("Y-m-d"))) / 86400; //距离天数
                    $data["visit"] = 0; //应到访视
                    $data['is_remind'] = 0; //0 不提醒
                    break;
                case 2://按就诊v，按period算应到访视，距离天数，推荐就诊日期
                    if ($period == -1) {
                        //所有访视 3个月
                        $visits = self::levelToVisitData($data["min_visit_at"], $data["visit_level"], 3, 3, 1, $data["actual_reserva"]);
                        //距离天数
                        $data["visit_diff"] = $visits["visit_diff"];

                        //推荐就诊日期
                        $data["suggest_reserva"] = $visits["visit_period_date"];
                        $data['next_followup'] = $data['next_followup_tmp'] > '0001-01-01' ? $data['next_followup_tmp'] : $visits["visit_period_date"];
                        //应到访视
                        $data["visit"] = $visits["visit_period"];
                    } else if ($period == -2) {
                        //仅半年访视 6个月
                        $visits = self::levelToVisitData($data["min_visit_at"], $data["visit_level"], 4, 6, 2, $data["actual_reserva"]);
                        //距离天数
                        $data["visit_diff"] = $visits["visit_diff"];

                        //推荐就诊日期
                        $data["suggest_reserva"] = $visits["visit_period_date"];
                        $data['next_followup'] = $data['next_followup_tmp'] > '0001-01-01' ? $data['next_followup_tmp'] : $visits["visit_period_date"];
                        //应到访视
                        $data["visit"] = $visits["visit_period"];
                    } else if ($period == -3) {
                        //仅整年访视 12个月
                        $visits = self::levelToVisitData($data["min_visit_at"], $data["visit_level"], 6, 12, 4, $data["actual_reserva"]);
                        //距离天数
                        $data["visit_diff"] = $visits["visit_diff"];
                        //推荐就诊日期
                        $data["suggest_reserva"] = $visits["visit_period_date"];
                        $data['next_followup'] = $data['next_followup_tmp'] > '0001-01-01' ? $data['next_followup_tmp'] : $visits["visit_period_date"];
                        //应到访视
                        $data["visit"] = $visits["visit_period"];
                    }
                    break;
                case 3://不提醒，更新推荐就诊日期，隐藏应到访视
                    $data["visit"] = 0;
                    $data['is_remind'] = 0;
                    $data['next_followup'] = '0001-01-01';
                    $data["suggest_reserva"] = '0001-01-01';
                    $data["visit_diff"] = $data["actual_reserva"] > '0001-01-01' ? $data["visit_diff"] : 0;
                    break;
            }

            if ($data["visit_diff"] >= 0) {
                //就诊
                $data["remaining_days"] = $data["visit_diff"];
                $data["overlap_days"] = "-1";
                $data["type"] = 1;
            } else {
                //漏诊
                $data["remaining_days"] = "-1";
                $data["overlap_days"] = abs($data["visit_diff"]);
                $data["type"] = 2;
            }
        }

        return $data;
    }

    /**
     * 更新单个用户的提醒周期
     * @param $params
     * @return array|bool
     */
    public function updateUserNotice($params)
    {

        if (!isset($params["user_id"]) || empty($params["user_id"]) || !isset($params["hosp_id"]) || empty($params["hosp_id"]) || !isset($params["dept_id"]) || empty($params["dept_id"])) {
            return false;
        }

        $data = self::explainData($params);

        if ($data === false) {
            return ['code' => -1000, 'msg' => '用户无记录'];
        }

        if (isset($params['plan_id']) && !empty($params['plan_id'])) {

            if ($params['plan_id'] != 1) {
                $periodType = $params['period_type'] ?? 2;
                $period = $params['period'] ?? -1;


                $data = self::periodInfo($periodType, $period, $data);
            }
        }

        unset($data["visit_diff"], $data['min_visit_at'], $data['next_followup_tmp']);

        $arr[] = $data;

        if (!empty($arr)) {
            $res = ZMmcPatientsNotice::insertPatientsNoticeNew($arr);

            if (!empty($res['code'])) {
                $msg = $res['msg'] ?? '信息错误';
                Log::error('提醒信息入库失败' . $msg);
                return ['code' => -1000, 'msg' => $msg];
            }
        }


        return ['code' => 1, 'msg' => 'success'];
    }


    /**
     * 更新单个医院
     * @param $hospId
     */
    public static function flushHospNotice($hospId)
    {
        Log::info($hospId . '-hosp flush start time' . date("Y-m-d H:i:s"));

        $count = ZVisitRecord::getTotalVisitHosp($hospId);

        Log::info($hospId . '-hosp flush count' . $count);

        if (empty($count)) {
            echo " hosp flush finish...";
            exit;
        }

        $max = ceil($count / self::LIMIT);
        $i = 0;
        $currentId = 0;

        while ($i <= $max) {

            $i++;
            //获取这个医院下的所有用户
            $userList = ZVisitRecord::getHospVisitAllList($hospId, $currentId, self::LIMIT);

            $userCount = count($userList) ?? 0; //总的用户

            if ($userCount > 0) {

                $currentIndex = $userCount - 1;
                $currentId = $userList[$currentIndex]->id;

                Log::info($hospId . '-hosp flush currentId' . $currentId);

                $arr = [];

                foreach ($userList as $user) {

                    $userId = $user->user_id ?? 0;
                    $hospId = $user->hosp_id ?? 0;

                    Log::info("用户相关检索开始 user_id = " . $userId);

                    if (!empty($userId) && !empty($hospId)) {

                        $data = self::explainData($user);

                        if ($data === false) {
                            continue;
                        }

                        //看下是否有修改随访计划
                        $isUpdatePlan = ZMmcUserManagePlanRecords::getManagePlanByUserId($data["user_id"], $data["hosp_id"], $data["dept_id"]);
                        if (!empty($isUpdatePlan)) {

                            Log::info("随访计划 user_id = " . $data["user_id"]);

                            if ($isUpdatePlan['plan_id'] > 1) {

                                $periodType = $isUpdatePlan['period_type'] ?? 2;
                                $period = $isUpdatePlan['period'] ?? -1;

                                if (!empty($periodType)) {

                                    $data = self::periodInfo($periodType, $period, $data);
                                }
                            }
                        }

                        unset($data["visit_diff"], $data['min_visit_at'], $data['next_followup_tmp']);

                        $arr[] = $data;
                    } else {
                        continue;
                    }
                }


                if (!empty($arr)) {
                    $res = ZMmcPatientsNotice::insertPatientsNoticeNew($arr);

                    if (!empty($res['code'])) {
                        $msg = $res['msg'] ?? '信息错误';
                        Log::error('提醒信息入库失败' . $msg);
                    }
                }
            } else {
                break;
            }
        }

        Log::info($hospId . '-hosp flush  end time' . date("Y-m-d H:i:s"));
        echo " hosp flush finish...";
        exit;
    }


    /**
     *  更新计算的时间
     * @return bool
     */
    public static function patientsHandleDate()
    {
        $date = date("Y-m-d");
        Log::info("patientsHandleDate 开始执行.. start time " . date("Y-m-d H:i:s"));

        try {
            $res = ZPituitaryPatientsNotice::updateDate($date);
            Log::info("patientsHandleDate 执行完毕..  end time " . date("Y-m-d H:i:s"));
        } catch (\Exception $exc) {
            Log::info("执行出错！ " . date("Y-m-d H:i:s"));
        }

        echo " patients notice finish...";

        return true;
    }


    /**
     * 获取部门科室下配置短信模板列表
     * @param $hospId
     * @param $deptId
     * @return array
     */
    public static function getSmsTemplates($hospId, $deptId)
    {
        $infos = ZPituitaryHospitalCustomSmsTemplate::getSmsTemplates($hospId, $deptId);
        //固定模板四个
//        $types = [502, 503, 504, 505];
        $types = [];
        foreach ($infos as $info) {
            $types[] = $info["sms_template_type"];
        }
        //所有的短信模板发送 只有#hospname#是需要被替换的 要保持一致 否则列表无法展示
        $hospInfo = ZHospMember::getHospInfo($hospId);
        $hospName = isset($hospInfo->name) ? $hospInfo->name : "";
        //找到这家医院的所有列表 并返回到页面
        $lists = ZPituitaryHospitalCustomSmsTemplate::getNoticeTemplate($types);
        foreach ($lists as &$list) {
            $list["content"] = str_replace("#hospname#", $hospName, $list["content"]);
        }
        return $lists;
    }


}
